/**
 * 
 */
package sg.edu.nus.iss.vmcs.payment;

import sg.edu.nus.iss.vmcs.customer.*;
import sg.edu.nus.iss.vmcs.price.PriceCalculator;
import sg.edu.nus.iss.vmcs.price.PricingContext;
import sg.edu.nus.iss.vmcs.store.Store;
import sg.edu.nus.iss.vmcs.store.StoreController;
import sg.edu.nus.iss.vmcs.system.Fault;
import sg.edu.nus.iss.vmcs.system.FaultType;
import sg.edu.nus.iss.vmcs.system.MainController;
import sg.edu.nus.iss.vmcs.util.Log;
import sg.edu.nus.iss.vmcs.util.VMCSException;

/**
 * @author moe
 * 
 */
public class CoinPayment implements Payment {

	private CoinReceiver coinReceiver = null;
	private ChangeGiver changeGiver = null;

	private PaymentController paymentCtrl = null;
	private MainController mainCtrl = null;

	private int amtToCollect = 0;
	private int amtCollected = 0;
	private int timeOutInSec = 0;

	public CoinPayment(PaymentController paymentController,
			MainController mainController) {
		this.paymentCtrl = paymentController;
		this.mainCtrl = mainController;
		coinReceiver = new CoinReceiver(this);
		changeGiver = new ChangeGiver(this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see sg.edu.nus.iss.vmcs.payment.Payment#completePayment(Boolean)
	 */
	public Boolean completePayment(Boolean status) {
		Boolean success = true;
		if (status == true) {
			boolean change_given = false;
			Log.LogIt("CoinPayment.completePayment:" + amtToCollect + ", " + amtCollected );
			if (amtToCollect < amtCollected) {
				try {
					change_given = changeGiver.giveChange(amtCollected
							- amtToCollect);
				} catch (VMCSException e) {
					e.printStackTrace();
					change_given = false;
				}
				if (!change_given) {
					success = false;
					Fault.getInstance().setState(FaultType.ChangeGiverFault);
				}
			}

			boolean cash_stored = false;
			try {
				cash_stored = coinReceiver.storeCash();
			} catch (VMCSException e) {
				e.printStackTrace();
				cash_stored = false;
			}
			if (!cash_stored) {
				success = false;
				Fault.getInstance().setState(FaultType.CoinReceiverFault);
			}

		} else {
			coinReceiver.stopReceive();
			coinReceiver.refundCash(true);
		}
		amtToCollect = 0;
		return success;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see sg.edu.nus.iss.vmcs.payment.Payment#processReceive(int)
	 */
	public void processReceive(int amount) {
		amtCollected = amount;
		paymentCtrl.receivingPayment(this);
		if (amtCollected>=amtToCollect){
			paymentCtrl.processMoneyReceive(amtCollected);			
		}else{
			coinReceiver.continueReceive();
		}
	}
	
	private int calcPrice(int orgPrice){
		PricingContext ctx = new PricingContext();
		ctx.setPriceCalculator(PriceCalculator.CASH_PRICE_CALCULATOR);
		return ctx.getPrice(orgPrice);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see sg.edu.nus.iss.vmcs.payment.Payment#startPayment(int,int)
	 */
	public void startPayment(int amountToCollect, int timeOutInSec) {
		this.amtToCollect = calcPrice(amountToCollect);
		this.timeOutInSec = timeOutInSec;
		amtCollected = 0;
		changeGiver.resetChange();
		changeGiver.displayChangeStatus();
		coinReceiver.startReceive();
	}

	public void invalidCoinInserted() {

	}

	public MainController getMainController() {
		return this.mainCtrl;
	}

	protected PaymentPanel getPanel() {
		return paymentCtrl.getPanel();
	}

	public void continueReceive(int amountToCollect) {
		// TODO Auto-generated method stub

	}

	protected CoinReceiver getCoinReceiver() {
		return coinReceiver;
	}

	protected ChangeGiver getChangeGiver() {
		return changeGiver;
	}

	protected void display() {
		changeGiver.displayChangeStatus();
		coinReceiver.setActive(false);
	}

	protected StoreController getStoreController() {
		return getMainController().getStoreController();
	}

	protected PaymentController getPaymentController(){
		return paymentCtrl;
	}

	public void setActive(boolean active) {
		getCoinReceiver().setActive(active);
		
	}
}
